#include <iostream>
#include <vector>
#include <string>
#include <unordered_map>
#include <chrono>
#include <thread>
#include <sw/redis++/redis++.h>

using namespace std;
using namespace sw::redis;

// get and set
void Test1(Redis& redis)
{
    // 清空下一数据库，避免之前残留数据的干扰
    cout << "set and get" << endl;

    redis.flushall();
    // 使用 set 设置 key
    redis.set("key1", "111");
    redis.set("key2", "222");
    redis.set("key3", "333");

    // 使用 get 获得 key 对应的 val
    auto val1 = redis.get("key1");
    cout << "val1:" << val1.value() << endl;

    auto val2 = redis.get("key2");
    cout << "val2:" << val2.value() << endl;

    auto val3 = redis.get("key3");
    cout << "val3:" << val3.value() << endl;

    auto val4 = redis.get("key4");
    // optional 可以隐式转换为 bool 类型的，如果不存在，返回 false
    if(val4)
        cout << "val4:" << val4.value() << endl;
    else 
        cout << "val4 not exists" << endl;
}

// exists
void Test2(Redis& redis)
{
    cout << "exists" << endl;
    redis.flushall();
    
    redis.set("key1", "111");
    auto ret1 = redis.exists("key1");
    // key1 exists
    cout << ret1 << endl;
    
    // key2 not exists
    auto ret2 = redis.exists("key2");
    cout << ret2 << endl;

    redis.set("key3", "333");
    auto ret3 = redis.exists({"key1", "key2", "key3"});
    cout << ret3 << endl;
}

// del
void Test3(Redis& redis)
{
    cout << "del" << endl;
    redis.flushall();

    redis.set("key1", "111");
    redis.set("key2", "222");
    // auto ret1 = redis.del("key1");
    auto ret = redis.del({"key1", "key2", "key3"});
    cout << ret << endl;

    ret = redis.exists({"key1", "key2"});
    cout << ret << endl;
}

// keys
void Test4(Redis& redis)
{
    cout << "keys" << endl;
    redis.flushall();

    redis.set("key1", "1");
    redis.set("key2", "2");

    // keys 的第二个参数是一个插入迭代器，需要先准备好一个保存结果的容器
    vector<string> ret;
    auto it = back_inserter(ret);
    redis.keys("*", it);
    
    // 打印获取到的 key
    for(auto& elem : ret)
    {
        cout << elem << endl;
    }
}

// expire and ttl
void Test5(Redis& redis)
{
    redis.flushall();
    cout << "expire and ttl" << endl;

    redis.set("key", "111");
    redis.expire("key", chrono::seconds(10));

    this_thread::sleep_for(3s);

    auto ret = redis.ttl("key");
    cout << "ret:" << ret << endl;
}

// type
void Test6(Redis& redis)
{
    redis.flushall();
    cout << "type" << endl;

    redis.set("key1", "111");
    cout << redis.type("key1") << endl;

    redis.lpush("key2", {"111", "222", "333"});
    cout << redis.type("key2") << endl;

    redis.hset("Joy", {make_pair("height", "172"), make_pair("age", "19"), make_pair("birthday", "7-28")});
    cout << redis.type("Joy") << endl;

    vector<string> ret;
    auto it = back_inserter(ret);
    redis.hgetall("Joy", it);
    for(auto& e : ret)
    {
        cout << e << endl;
    }
}

int main()
{
    Redis redis("tcp://127.0.0.1:6379");

    // Test1(redis);
    // Test2(redis);
    // Test3(redis);
    // Test4(redis);
    // Test5(redis);
    Test6(redis);

    return 0;
}